package com.uusoft.core.utils.db;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.uusoft.core.exception.CommException;
import com.uusoft.core.utils.Constant;
import com.uusoft.core.utils.PropertiesParser;

/**
 * 数据源连接管理类
 * 
 * @author shisheng.lian
 * 
 */
public class ConnectionManager {
	private static DataSourceAdapter dsa;

	private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
	static {
		try {
			PropertiesParser pp = new PropertiesParser();
			String dataSourceAdapterClsStr = pp.getStringProperty(Constant.DATASOURCE_ADAPTER, C3p0DataSourceAdapter.class.getName());
			Class<?> dataSourceAdapterCls = Class.forName(dataSourceAdapterClsStr);
			Object dataSourceAdapter = dataSourceAdapterCls.newInstance();
			dsa = (DataSourceAdapter) dataSourceAdapter;
		} catch (Exception e) {
			throw new CommException("获取数据源适配器失败!", e);
		}
	}

	public static DataSource getDataSource() {
		return dsa.getDataSource();
	}

	public static Connection getConnection() throws SQLException {
		try {
			// 得到当前线程上绑定的连接
			Connection conn = tl.get();
			if (conn == null) { // 代表线程上没有绑定连接
				conn = getDataSource().getConnection();
				tl.set(conn);
			}
			return conn;
		} catch (Exception e) {
			throw new CommException(e);
		}
	}

	public static void startTransaction() {
		try {
			// 得到当前线程上绑定连接开启事务
			Connection conn = tl.get();
			if (conn == null) { // 代表线程上没有绑定连接
				conn = getDataSource().getConnection();
				tl.set(conn);
			}
			conn.setAutoCommit(false);
		} catch (Exception e) {
			throw new CommException(e);
		}
	}

	public static void commitTransaction() {
		try {
			Connection conn = tl.get();
			if (conn != null) {
				conn.commit();
			}
		} catch (Exception e) {
			throw new CommException(e);
		}
	}

	public static void closeConnection() {
		try {
			Connection conn = tl.get();
			if (conn != null) {
				conn.close();
			}
		} catch (Exception e) {
			throw new CommException(e);
		} finally {
			tl.remove(); // 千万注意，解除当前线程上绑定的链接（从threadlocal容器中移除对应当前线程的链接）
		}
	}

}